/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo
 * All rights reserved.
 */
package ac.jp.u_tokyo.SyncLib.language3;

import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import sun.awt.VariableGridLayout;

import ac.jp.u_tokyo.SyncLib.language.Const;
import ac.jp.u_tokyo.SyncLib.language.ConstRef;
import ac.jp.u_tokyo.SyncLib.language.EvaluationFailedException;
import ac.jp.u_tokyo.SyncLib.language.GraphCombinatorBody;
import ac.jp.u_tokyo.SyncLib.language.NativeSyncBody;
import ac.jp.u_tokyo.SyncLib.language.SyncBody;

public class EqualExpr extends FixedParaSyncConstructBase
{

	public static class EqualConstPart extends ConstPart{
		Const _const;
		

		public EqualConstPart(Const const1)
		{
			super();
			_const = const1;
		}

		@Override
		public void addBody(GraphCombinatorBody body,
				Collection<String> genericParas, Var var)
				throws EvaluationFailedException
		{
			SyncBody result = NativeSyncFactory.createEqual(_const, _const.getLine());
			List<Var> para = new LinkedList<Var>();
			para.add(var);
			body.addConnection(result, Helper.higherVar2LowerVar(para));
		}

		
	}
	
	public static class EqualConstVarRefPart extends ConstVarRefPart {
		public EqualConstVarRefPart(String name, int line)
		{
			super();
			_name = name;
			_line = line;
		}
		@Override
		protected ConstPart createConst()
		{
			return new EqualConstPart(new ConstRef(_line, _name));
		}

	}
	
	private Part _left;
	private Part _right;
	
	public EqualExpr(int line, Part left, Part right)
	{
		super(line);
		_left = left;
		_right = right;
	}

	@Override
	public void addBody(GraphCombinatorBody body,
			Collection<String> genericParas) throws EvaluationFailedException
	{
		Set<Var> varUsed = getConnectionVars(genericParas);
		if (varUsed.size() == 2) {
			SyncBody result = NativeSyncFactory.createId(false, getLine());
			List<Var> para = new LinkedList<Var>();
			para.add(_left.getConnectionVar(genericParas));
			para.add(_right.getConnectionVar(genericParas));
			body.addConnection(result, Helper.higherVar2LowerVar(para));
		}
		
		Var commonVar;
		if (varUsed.size() == 1) {
			commonVar = varUsed.iterator().next();  
		}
		else {
			commonVar = Helper.createNewVar(body);
		}
		
		
		_right.addBody(body, genericParas, commonVar);
		_left.addBody(body, genericParas, commonVar);
		
	}

	@Override
	public Set<Var> getVarUsed(Collection<String> genericParas)
			throws EvaluationFailedException
	{
		Set<Var> result = new HashSet<Var>();
		result.addAll(_left.getVarUsed(genericParas));
		result.addAll(_right.getVarUsed(genericParas));
		return result;
	}

	private Set<Var> getConnectionVars(Collection<String> genericParas)
			throws EvaluationFailedException
	{
		Set<Var> result = new HashSet<Var>();
		if (_left.getConnectionVar(genericParas) != null) {
			Var var = _left.getConnectionVar(genericParas);
			result.add(var);
		}
		if (_right.getConnectionVar(genericParas) != null) {
			Var var = _right.getConnectionVar(genericParas);
			result.add(var);
		};
		return result;
	}

}
